import os
import re
import requests
from io import BytesIO
from xml.etree import ElementTree as ET
from docx import Document
from docx.shared import Inches
from docx.oxml import OxmlElement

"""
	把xml处理下，写入到doc中。
	需要传入doc模板、输出路径、文章标题等。
	需要调用save方法才能保存。
"""


class DocxConverter:
	def __init__(self, template_path: str = None, output_dir: str = None, title: str = "未命名", main_title: str = None):
		"""
		参数:
		template_path，docx模板的路径，默认是doc_files下的template项目的blank.docx。
		output_dir : 输出的文件，默认是默认是doc_files下的vip_files。
		title:文件名
		main_title:如果有的话，就是文档的标题。
		"""
		self.title = title
		self.template_path = template_path
		self.output_dir = output_dir #文件夹路径
		self._ensure_output_path() #检查下是否有效
		self.save_path = os.path.join(self.output_dir, f"{title}.docx") #文件最终保存的路径
		self.document = self._load_template() #初始化模板
		self._clear_document() #清除模版格式
		if not main_title:
			self.document.add_heading(self.title,1)
		else:
			self.document.add_heading(main_title,1)#添加主标题

	def _load_template(self) -> Document:
		# print(self.template_path)
		"""加载模板文件或默认文件"""
		if self.template_path and os.path.exists(self.template_path):
			return Document(self.template_path)
		else:
			template_file = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'doc_files',"template", "blank.docx")
			return Document(template_file)

	def _ensure_output_path(self):
		"""确保保存路径有效"""
		# print(self.output_dir,"这是docx里的路径")
		if not self.output_dir or not os.path.exists(os.path.dirname(self.output_dir)):
			default_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'doc_files','vip_files')
			self.output_dir = default_dir

	def _clear_document(self):
		"""清空文档中的所有段落"""
		for paragraph in self.document.paragraphs:
			p = paragraph._element
			p.getparent().remove(p)
			p._element = p._p = None

	def add_text_to_docx(self, text_string: str, section_title=None) -> bool:
		"""把字符串格式的文字插入到文章中去"""
		# print(f"这是docx里的add_text_to_docx{text_string},{section_title}")
		if section_title:
			self.document.add_heading(section_title)
		# 替换多个连续的换行符为单个换行符
		processed_text = re.sub(r'\n+', '\n', text_string)
		# 按照换行符分割字符串
		paragraphs = processed_text.split('\n')
		for paragraph_text in paragraphs:
			paragraph_text = paragraph_text.strip()
			# if len(paragraph_text) < 30:
			# 	continue
			if paragraph_text[-1] == ',' or paragraph_text[-1] == '，':
				continue
			paragraph = self.document.add_paragraph()
			lines = paragraph_text.split('\n')
			for i, line in enumerate(lines):
				line = line.strip()
				# if len(line) < 30:
				# 	continue
				# 如果最后一个字符是“,",print出来
				if line[-1] == ',' or line[-1] == '，':
					continue
				if i > 0:
					# Add line break
					line = line.strip()
					run = paragraph.add_run()
					br = OxmlElement('w:br')
					run._r.append(br)
				# Add line text
				paragraph.add_run(line)
		return True

	def add_xml_to_docx(self, xml_string: str, section_title=None) -> bool:
		"""解析XML字符串并将其内容添加到docx文档中"""
		try:
			root = ET.fromstring(xml_string)
		except ET.ParseError as e:
			print(f"XML解析错误: {e}")
			print(xml_string)
			return False

		if section_title:
			self.document.add_heading(section_title)

		self.traverse_xml(root)
		return True

	def traverse_xml(self, root: ET.Element):
		"""递归遍历XML元素并添加到文档"""
		for child in root:
			self._add_xml_to_document(child)
			# 只对包含子元素的节点递归
			if len(child) > 0:
				self.traverse_xml(child)

	def _add_xml_to_document(self, element: ET.Element):
		"""根据XML元素类型将其内容添加到文档"""
		if element.tag.startswith('title'):
			title_level = int(element.tag[-1]) if element.tag[-1].isdigit() else 1
			if element.text.strip()[-1] != ',' and element.text.strip()[-1] != '，':
				self.document.add_heading(element.text.strip(), level=title_level+1)
		elif element.tag == 'paragraph':
			if element.text is not None and element.text.strip()[-1] != ',' and element.text.strip()[-1] != '，':
				self.document.add_paragraph(element.text.strip())
		elif element.tag == 'img':
			img_url = element.get('src')
			if img_url:
				try:
					response = requests.get(img_url)
					response.raise_for_status()
					image_stream = BytesIO(response.content)
					self.document.add_picture(image_stream, width=Inches(6))
				except requests.RequestException as e:
					print(f"图片加载错误: {e}")

	def save_output(self):
		"""保存生成的docx文档"""
		self.document.save(self.save_path)
		print(f"=============== 保存成功：{self.save_path} =============")


if __name__ == "__main__":
	xml_string = '''
    <content>
        <paragraph>生活中的美无处不在，它可能是一朵绽放的花朵，可能是陌生人的一个微笑，也可能是一次心灵的触动。只要我们拥有一双善于发现的眼睛，一颗敏感细腻的心，就能在平凡的生活中找到那些令人心动的美好瞬间。让我们用心去感受、去珍惜，让生活因为这些美而更加绚丽多彩。</paragraph>
    </content>
    '''
	text_string="这是一个\n\n段落这是这是一个段落这是这\n\n\n\n是一个段落这是这是一个段落这\n是这是一个段落这是这是一个段落这是"

	xml_to_docx = DocxConverter()
	xml_to_docx.add_text_to_docx(text_string=text_string)
	xml_to_docx.save_output()
